/*
 * phonebook.cpp - phonebook GUI and database
 *
 * Copyright (C) 2010-2011 Serge Begger
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "phonebook.h"
#include "ui_phonebook.h"

phonebook::phonebook(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::phonebook)
{
    ui->setupUi(this);
    ui->nwbackButton->hide();
    this->hide();
    openDb = initDbConnection();
    syncml = new syncmlbt(this);
    connect (syncml,SIGNAL(endSync()),this,SLOT(parseVcard()));

    modelPhone = new QSqlRelationalTableModel(this);
    modelPhone->setTable("phones");
    modelPhone->select();

    modelName = new QSqlRelationalTableModel(this);
    modelName->setTable("names");
    modelName->select();

    ui->numberTableView->setModel(modelPhone);
    ui->numberTableView->setColumnHidden(0,true);
    ui->numberTableView->setColumnHidden(2,true);

    ui->nameTableView->setModel(modelName);
    ui->nameTableView->setColumnHidden(0,true);
    if (modelName->rowCount() != 0)
        ui->nameTableView->selectRow(0);

    uniqueNameId = 0;
    uniquePhoneId = 0;
    on_nameTableView_pressed(modelName->index(0,1));
    currNumber = "";
    currName = "";
}

phonebook::~phonebook()
{
    if (!db.isOpen()) {
        db.close();
    }
    delete ui;
}

void phonebook::on_nameTableView_pressed(QModelIndex index)
{
    currName = index.data().toString();
    if (index.isValid()) {
        modelPhone->setFilter("nameid = " + modelName->index(index.row(),0).data().toString());
        if (modelPhone->rowCount() != 0)
            ui->numberTableView->selectRow(0);
    } else  {
        modelPhone->setFilter(QString());
    }
}

void phonebook::on_numberTableView_pressed(QModelIndex index)
{
    if (index.isValid()) {
        currNumber = index.data().toString();
    }
}

void phonebook::on_stCallButton_pressed()
{    
    if (modelPhone->rowCount() > 1 && ui->stackedWidget->currentIndex() == 0)
    {
        ui->stackedWidget->setCurrentIndex(1);
        ui->nwbackButton->show();
    } else if (modelPhone->rowCount() > 1 && ui->stackedWidget->currentIndex() == 1) {
        emit selectNumber();
        on_backButton_pressed();
    } else {
        currNumber = modelPhone->index(0,1).data().toString();
        emit selectNumber();
        on_backButton_pressed();
    }
}

void phonebook::on_pushButUp_pressed()
{
    QTableView *currTV;
    if (ui->stackedWidget->currentIndex() == 0)
        currTV = ui->nameTableView;
    else
        currTV = ui->numberTableView;

    int currRow = currTV->currentIndex().row() - 1;
    if (currRow < 0)
        currRow = 0;
    currTV->selectRow(currRow);
    on_nameTableView_pressed(currTV->currentIndex());
}

void phonebook::on_pushButDw_pressed()
{
    QTableView *currTV;
    int rowCount;
    if (ui->stackedWidget->currentIndex() == 0) {
        currTV = ui->nameTableView;
        rowCount = modelName->rowCount();
    } else {
        currTV = ui->numberTableView;
        rowCount = modelPhone->rowCount();
    }

    int currRow = currTV->currentIndex().row() + 1;
    if (currRow > rowCount)
        currRow = rowCount;
    currTV->selectRow(currRow);
    on_nameTableView_pressed(currTV->currentIndex());
}

void phonebook::on_nwbackButton_pressed()
{
    ui->stackedWidget->setCurrentIndex(0);
    ui->nwbackButton->hide();
}

void phonebook::on_backButton_pressed()
{
    this->hide();
    emit hideWidget();
}

void phonebook::on_syncButton_pressed()
{
    myMessage message(0);
    message.exec(3,"Sync contacts?");
    if (!message.result)
        return;
    if(btaddr.isEmpty())
        return;
    if (syncml->search(btaddr))
        syncml->startSync();
}

QString phonebook::findCharset(QByteArray data)
{
    int ch = data.indexOf("CHARSET");
    int chout = 0;
    int chout1 = data.indexOf(";",ch);
    int chout2 = data.indexOf(":",ch);
    if(chout1 > 0 && chout2 > 0)
        chout = qMin(chout1,chout2);
    else if(chout2 > 0)
        chout = chout2;
    else
        chout = chout1;
    return data.mid(ch+8,chout-ch-8);
}

void phonebook::parseVcard()
{
    removeAllRecords();
    for (int i = 0; i < syncml->vCards->size(); ++i) {
        QByteArray vCard = syncml->vCards->at(i);
        QString charset;QString name;
        QByteArray lineName;
        QList<QString> phone;
        QList<QByteArray> lines = vCard.split('\n');
        for(int i = 0 ; i < lines.size(); i++) {
            QByteArray line = lines.at(i);
            if (line.startsWith("N"))  {
                charset = findCharset(line);
                if(charset.isEmpty())
                    name = line.mid(2,line.size()-2);
                else
                    lineName.append(line.mid(line.indexOf(":")+1));
            }else if (line.startsWith("FN"))  {
                name.clear();
                lineName.clear();
                charset = findCharset(line);
                if(charset.isEmpty())
                    name = line.mid(2,line.size()-2);
                else
                    lineName.append(line.mid(line.indexOf(":")+1));
            }else if( line.startsWith("=") ){
                lineName.append(line.mid(1));
            }else if (line.startsWith("TEL")) {
                if (!charset.isEmpty()) {
                    lineName = QByteArray::fromPercentEncoding(lineName,*("="));
                    QTextCodec *codec = QTextCodec::codecForName(charset.toAscii());
                    QList<QByteArray> strName = lineName.split(';');
                    foreach (QByteArray part, strName) {
                        if (!part.isEmpty()) {
                            QString tmpname = codec->toUnicode(part);
                            if (name.indexOf(tmpname) < 0)
                                name = name + " " + tmpname;
                        }
                    }
                }
                int ch = line.indexOf(":");
                phone.append(line.mid(ch+1));

            } else
                continue;
        }
        if(!name.isEmpty()) {
            int nameId = addName(name);
            for(int i = 0 ; i < phone.size(); i++) {
                QString number = phone.at(i);
                addNumber(number, nameId);
            }
        }
    }
    syncml->vCards->clear();
}

int phonebook::addName(QString name)
{
    int id = generateNameId();
    int row = modelName->rowCount();
    modelName->insertRows(row, 1);
    modelName->setData(modelName->index(row, 0), id);
    modelName->setData(modelName->index(row, 1), name);
    modelName->submitAll();
    return id;
}

int phonebook::addNumber(QString number, int nameId)
{
    int id = generatePhoneId();
    int row = modelPhone->rowCount();
    modelPhone->insertRows(row, 1);
    modelPhone->setData(modelPhone->index(row, 0), id);
    modelPhone->setData(modelPhone->index(row, 1), number);
    modelPhone->setData(modelPhone->index(row, 2), nameId);
    modelPhone->submitAll();
    return id;
}

int phonebook::generateNameId()
{
    uniqueNameId += 1;
    return uniqueNameId;
}

int phonebook::generatePhoneId()
{
    uniquePhoneId += 1;
    return uniquePhoneId;
}

void phonebook::removeAllRecords()
{
    modelName->removeRows(0,modelName->rowCount());
    modelPhone->removeRows(0,modelPhone->rowCount());
    uniqueNameId = 0;
    uniquePhoneId = 0;
}

bool phonebook::initDbConnection()
{
    if(QSqlDatabase::contains(QSqlDatabase::defaultConnection)) {
        db = QSqlDatabase::database();
    } else {
        db = QSqlDatabase::addDatabase("QSQLITE");
    }
    db.setDatabaseName(QDir::homePath() + "/qcarpc.db");
    if (!db.open()) {
        myMessage message(0);
        message.exec(0,"Cannot open SQLite database!");
        return false;
    }

    QStringList dbtables = db.tables(QSql::Tables);
    if (dbtables.contains( tr("names"), Qt::CaseInsensitive)) {
        return true;
    } else {
        QSqlQuery query;

        query.exec("create table names (id int primary key, "
                                     "NAME varchar(50) )");

        query.exec("create table phones (phoneid int primary key, "
                                     "NUMBER varchar(20), "
                                     "nameid int)");
    }
    return true;
}
